-- ======================================================================
-- Hell Logic Sniffer Addon
--
-- Copyright 2013 Hell-Prototypes
--
-- http://www.hellprototypes.com/
-- ======================================================================

ModuleClass = "LS_DECODER"
ModuleName  = "CUSTOM"
ModuleAlias = "MiDea IR"
ModuleParam1= "CH Number"
ModuleTip   = [[
Infrared Decoder use CUSTOM addon interface

Note: 解码美的中央空调的红外遥控编码
]]

g_sampling_period = 0
g_NBT_bit_len = 0

g_ch_negedge_table = {}
g_ch_negedge_table_index = 1
g_channel_bit_index = 0

g_bit_stuffing_count = 0
g_last_bit_level = 0

g_byte_mask = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}

function main ()
    -- param check
    if type(LS_PARAM) ~= "table" then
    	LS_API.MessageBox("<IR> LS_PARAM was not a table class")
		return
    end
    if #LS_PARAM ~= 6 then
    	LS_API.MessageBox("<IR> LS_PARAM's size must = 6, size = " .. #LS_PARAM)
    end

    g_ch_num = LS_PARAM[1]
    local common_param = LS_API.GetCommonParameter()
	LS_API.DebugMsg("common_param len = ".. #common_param)
	if #common_param > 0 then
		g_sampling_period = common_param[1]
	end

	--get channel data
	g_ch_negedge_table = LS_API.GetChannelNegedgeTable(g_ch_num)
	if type(g_ch_negedge_table) ~= "table" then
    	LS_API.MessageBox("<IR>Read channel data fail...")
		return
    end

    if #g_ch_negedge_table == 0 then
    	LS_API.MessageBox("<IR>No data in selected channel : " .. g_ch_num)
		return
    end
    LS_API.DebugMsg("g_ch_negedge_table size = ".. #g_ch_negedge_table)
    LS_API.DebugMsg("last package start bit at = ".. g_ch_negedge_table[#g_ch_negedge_table - 1])

	g_NBT_bit_len = math.floor(1600000/g_sampling_period)--Bit threshold 1.6MS
	LS_API.DebugMsg("g_NBT_bit_len = ".. g_NBT_bit_len)

	g_ch_negedge_table_index = 2
	local curr_bit_offset = g_ch_negedge_table[g_ch_negedge_table_index]
	local last_bit_offset = curr_bit_offset
	local byte_sampling_index = 3
	local l_decode_out = {}
	local l_byte_data = 0
	while g_ch_negedge_table_index < #g_ch_negedge_table do
		--find first valid byte and offset half bit
		if byte_sampling_index == 3 then
			l_decode_out[1] = curr_bit_offset
			l_decode_out[2] = 0 -- init to 0
		end
		curr_bit_offset = find_next_failling_edge(last_bit_offset)
		
		if curr_bit_offset - last_bit_offset < 2 * g_NBT_bit_len then
			if curr_bit_offset - last_bit_offset > g_NBT_bit_len then
				l_byte_data = l_byte_data + g_byte_mask[9 - (byte_sampling_index - 2)]
			end
			l_decode_out[byte_sampling_index] = last_bit_offset
			byte_sampling_index = byte_sampling_index + 1
			
			if byte_sampling_index == 11 then
				byte_sampling_index = 3
				l_decode_out[2] = l_byte_data
				local PushBack_ret = LS_API.DecodeElementPushBack(l_decode_out)
				if PushBack_ret ~= 0 then
					LS_API.MessageBox("<IR> Fail to push decode result to host... ret =" .. PushBack_ret)
					return
				else
					--LS_API.DebugMsg("=== g_byte_data = ".. g_byte_data)
				end
				l_decode_out = {}
				l_byte_data = 0
			end
		end
		last_bit_offset = curr_bit_offset
	end
end
-- -----------------------------------------------------------------------------
function find_next_failling_edge(base)
	local offset
    while g_ch_negedge_table_index <= #g_ch_negedge_table do
    	offset = g_ch_negedge_table[g_ch_negedge_table_index]
    	if offset > base then
    		return offset
    	end
    	g_ch_negedge_table_index = g_ch_negedge_table_index + 1
    end
	return 0
end
